﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using StairsModuleAndEdit.HYElevator.DataInfo;
using StairsModuleAndEdit.HYElevator.Manage;
using StairsModuleAndEdit.HYPutElevator.Kit;
using StairsModuleAndEdit.StairsModel.CommonUnit;

namespace StairsModuleAndEdit.HYElevator.Kit
{
	internal class SetElevator
	{
		public SetElevator(ExternalCommandData CmdData, ElevatorSettingParam val, Dictionary<ViewPlan, bool> FloorLevels, List<XYZ> pts)
		{
			this.m_CmdData = CmdData;
			this.m_doc = this.m_CmdData.Application.ActiveUIDocument.Document;
			this.m_ElevatorSettings = val;
			this.m_DicFloorLevels = FloorLevels;
			this.m_pt1 = pts[0];
			this.m_pt2 = pts[1];
			this.m_pt3 = pts[2];
		}

		private Group Set2dCurves(double dAngle, XYZ insertPt, string strLayerStop)
		{
			List<Curve> list = Draw2DLegend.Draw(this.m_doc, this.m_ElevatorSettings.m_liftCarParam, this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos, this.dOffset, insertPt);
			List<ElementId> list2 = new List<ElementId>();
			foreach (Curve curve in list)
			{
				ModelCurve modelCurve = this.m_doc.CreateModelLine(curve.GetEndPoint(0), curve.GetEndPoint(1));
				list2.Add(modelCurve.Id);
			}
			Group group = this.m_doc.Create.NewGroup(list2);
			GroupType groupType = group.GroupType;
			if (groupType.CanBeRenamed)
			{
				string text = "Elevator#";
				text += strLayerStop;
				text += "#";
				text += groupType.Name;
				text.Trim();
				groupType.Name = text;
			}
			Line line = Line.CreateUnbound(insertPt, XYZ.BasisZ);
			ElementTransformUtils.RotateElement(this.m_doc, group.Id, line, dAngle);
			return group;
		}

		private void GetElevatorCommonent(ref string strLayerStop, ref int nStopNum, ref double dLiftH)
		{
			List<ViewPlan> list = new List<ViewPlan>();
			foreach (KeyValuePair<ViewPlan, bool> keyValuePair in this.m_DicFloorLevels)
			{
				if (keyValuePair.Value)
				{
					list.Add(keyValuePair.Key);
					nStopNum++;
				}
			}
			Level genLevel = list.First<ViewPlan>().GenLevel;
			Level genLevel2 = list.Last<ViewPlan>().GenLevel;
			strLayerStop = genLevel.Name + "@";
			strLayerStop += genLevel2.Name;
			dLiftH = Math.Abs(genLevel2.Elevation - genLevel.Elevation);
		}

		private void SetSettings(FamilyInstance ElevatorInstance)
		{
			Parameter parameter = ElevatorInstance.GetParameter("电梯类型");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(MatchType.GetElevatorType(this.m_ElevatorSettings.m_baseParam.m_ElevatorType));
			}
			parameter = ElevatorInstance.GetParameter("电梯编号");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_baseParam.m_strName);
			}
			parameter = ElevatorInstance.GetParameter("额定载重量");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_baseParam.m_RatedLoad);
			}
			parameter = ElevatorInstance.GetParameter("厅门型式");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(MatchType.GetDoorType(this.m_ElevatorSettings.m_doorParam.m_DoorType));
			}
			if (this.m_ElevatorSettings.m_doorParam.m_DoorType == DoorType.MIDTYPE)
			{
				parameter = ElevatorInstance.GetParameter("中分门可见性");
				if (parameter != null && !parameter.IsReadOnly)
				{
					parameter.Set(1);
				}
				parameter = ElevatorInstance.GetParameter("旁开门可见性");
				if (parameter != null && !parameter.IsReadOnly)
				{
					parameter.Set(0);
				}
			}
			else
			{
				parameter = ElevatorInstance.GetParameter("中分门可见性");
				if (parameter != null && !parameter.IsReadOnly)
				{
					parameter.Set(0);
				}
				parameter = ElevatorInstance.GetParameter("旁开门可见性");
				if (parameter != null && !parameter.IsReadOnly)
				{
					parameter.Set(1);
				}
			}
			parameter = ElevatorInstance.GetParameter("门宽");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_doorParam.m_nDoorWidth);
			}
			parameter = ElevatorInstance.GetParameter("门高");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_doorParam.m_nDoorHeight);
			}
			parameter = ElevatorInstance.GetParameter("备注");
			if (parameter != null && !parameter.IsReadOnly && this.m_ElevatorSettings.isAlarm)
			{
				parameter.Set("兼消防电梯");
			}
			parameter = ElevatorInstance.GetParameter("轿厢宽");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_liftCarParam.m_nCarWidth);
			}
			parameter = ElevatorInstance.GetParameter("轿厢深");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_liftCarParam.m_nCarDepeth);
			}
			parameter = ElevatorInstance.GetParameter("轿厢高");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_liftCarParam.m_nCarHeight);
			}
			parameter = ElevatorInstance.GetParameter("平衡块位置");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(MatchType.GetBPos(this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos));
			}
			parameter = ElevatorInstance.GetParameter("额定速度");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(this.m_ElevatorSettings.m_otherParam.m_dRatedSpeed * 1000.0 / 304.8);
			}
		}

		private bool SetAllElevator(ViewPlan FirstLayer, Dictionary<ElementId, ElementId> DicHostWalls)
		{
			this.FindFamilySymbol();
			if (this.m_ESymbol == null || this.m_FistLayerESymbol == null)
			{
				return false;
			}
			double dAngle = 0.0;
			XYZ xyz = null;
			XYZ xyz2 = null;
			this.CalAngleAndInsertPt(ref dAngle, out xyz, out xyz2);
			string empty = string.Empty;
			int nStopNum = 0;
			double dLiftHeight = 0.0;
			this.GetElevatorCommonent(ref empty, ref nStopNum, ref dLiftHeight);
			List<ElementId> list = new List<ElementId>();
			list.Clear();
			Element element = null;
			foreach (KeyValuePair<ViewPlan, bool> keyValuePair in this.m_DicFloorLevels)
			{
				ViewPlan key = keyValuePair.Key;
				if (DicHostWalls.ContainsKey(key.GenLevel.Id))
				{
					double elevation = key.GenLevel.Elevation;
					XYZ xyz3 = new XYZ(xyz.X, xyz.Y, elevation);
					ElementId elementId = DicHostWalls[key.GenLevel.Id];
					Wall wall = this.m_doc.GetElement(elementId) as Wall;
					Face faceByNoraml = CalHostForEachLayer.GetFaceByNoraml(wall, xyz2, key);
					xyz2 = faceByNoraml.ComputeNormal(UV.Zero);
					ModifyRoom modifyRoom = new ModifyRoom(this.m_doc, key, this.m_ElevatorSettings.m_baseParam.m_strName);
					if (!keyValuePair.Value)
					{
						double num = Common.MMToFeet(250.0);
						XYZ insertPt = xyz3 + xyz2 * num;
						Group group = this.Set2dCurves(dAngle, insertPt, empty);
						Parameter parameter = group.get_Parameter(BuiltInParameter.GROUP_LEVEL);
						if (parameter != null && !parameter.IsReadOnly)
						{
							parameter.Set(key.GenLevel.Id);
						}
						list.Add(group.GroupType.Id);
						modifyRoom.Run(group);
					}
					else
					{
						Curve curve = (wall.Location as LocationCurve).Curve;
						this.CorrectElevatorInstanceInsert(curve, xyz2, ref xyz3);
						xyz3 = new XYZ(xyz3.X, xyz3.Y, elevation);
						FamilyInstance familyInstance;
						if (key.Id == FirstLayer.Id)
						{
							familyInstance = this.m_doc.Create.NewFamilyInstance(xyz3, this.m_FistLayerESymbol, wall, 0);
							element = familyInstance;
						}
						else
						{
							familyInstance = this.m_doc.Create.NewFamilyInstance(xyz3, this.m_ESymbol, wall, 0);
						}
						this.m_doc.Regenerate();
						this.CorrectElevatorInstance(xyz2, xyz3, familyInstance);
						ElevatorXDataManager.WriteElevatorComment(familyInstance, empty, nStopNum, dLiftHeight, null);
						modifyRoom.Run(familyInstance);
					}
				}
			}
			if (element != null)
			{
				ElevatorXDataManager.WriteElevatorComment(element, empty, nStopNum, dLiftHeight, list);
				return true;
			}
			return false;
		}

		private void CorrectElevatorInstanceInsert(Curve BaseCrv, XYZ Direction, ref XYZ insertPtEach)
		{
			IntersectionResult intersectionResult = BaseCrv.Project(insertPtEach);
			insertPtEach = intersectionResult.XYZPoint;
			if (this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos == BlanceWeightPos.BALLEFT)
			{
				XYZ xyz = Direction.CrossProduct(XYZ.BasisZ).Normalize();
				insertPtEach -= xyz * this.dOffset;
				return;
			}
			if (this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos == BlanceWeightPos.BALRIGHT)
			{
				XYZ xyz2 = Direction.CrossProduct(XYZ.BasisZ).Normalize();
				insertPtEach += xyz2 * this.dOffset;
			}
		}

		private void CorrectElevatorInstance(XYZ Direction, XYZ insertPtEach, FamilyInstance ElevatorIns)
		{
			(ElevatorIns.Location as LocationPoint).Point = insertPtEach;
			XYZ xyz = ElevatorIns.FacingOrientation.Normalize();
			if (!xyz.IsAlmostEqualTo(Direction))
			{
				ElevatorIns.flipFacing();
				if (this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos == BlanceWeightPos.BALRIGHT)
				{
					ElevatorIns.flipHand();
				}
			}
			else if (this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos == BlanceWeightPos.BALLEFT)
			{
				ElevatorIns.flipHand();
			}
			this.m_doc.Regenerate();
			this.SetSettings(ElevatorIns);
		}

		private void CalAngleAndInsertPt(ref double dAngle, out XYZ PtInsert, out XYZ Direct)
		{
			YJKLine hyline = new YJKLine(this.m_pt1, this.m_pt2);
			bool flag = hyline.IsPointOnLine(this.m_pt3);
			XYZ xyz = this.m_pt2 - this.m_pt1;
			xyz.Normalize();
			if (flag)
			{
				Direct = xyz.CrossProduct(XYZ.BasisZ).Normalize();
			}
			else
			{
				XYZ project = hyline.GetProject(this.m_pt3);
				Direct = this.m_pt3 - project;
				Direct = Direct.Normalize();
			}
			dAngle = XYZ.BasisY.AngleOnPlaneTo(Direct, XYZ.BasisZ);
			PtInsert = new XYZ((this.m_pt1.X + this.m_pt2.X) / 2.0, (this.m_pt1.Y + this.m_pt2.Y) / 2.0, 0.0);
			while (!Common.IsDoubleLessThanZero(dAngle - Math.PI*2) || Common.IsDoubleEquals(dAngle, Math.PI*2, 1E-09))
			{
				dAngle -= Math.PI*2;
			}
		}

		private void FindFamilySymbol()
		{
			KindToFamily instance = KindToFamily.GetInstance();
			FamilyKind key;
			key.SelBalPos = this.m_ElevatorSettings.m_otherParam.m_BalanceWeightPos;
			key.SelElevatorType = this.m_ElevatorSettings.m_baseParam.m_ElevatorType;
			key.bIsFirstLayer = true;
			string FirstTypeName = instance.DicFamilyName[key];
			key.bIsFirstLayer = false;
			string OtherTypeName = instance.DicFamilyName[key];
			LoadFamily instance2 = LoadFamily.GetInstance(this.m_CmdData);
			if (instance2 == null)
			{
				return;
			}
			List<ElementId> lstFamily = instance2.m_lstFamily;
			ElementId elementId = lstFamily.Find((ElementId e) => this.m_doc.GetElement(e).Name == FirstTypeName);
			Family family = this.m_doc.GetElement(elementId) as Family;
			ElementId elementId2 = lstFamily.Find((ElementId e) => this.m_doc.GetElement(e).Name == OtherTypeName);
			Family family2 = this.m_doc.GetElement(elementId2) as Family;
			if (family != null)
			{
				this.m_FistLayerESymbol = (this.m_doc.GetElement(family.GetFamilySymbolIds().First<ElementId>()) as FamilySymbol);
				if (!this.m_FistLayerESymbol.IsActive)
				{
					this.m_FistLayerESymbol.Activate();
				}
			}
			if (family != null)
			{
				this.m_ESymbol = (this.m_doc.GetElement(family2.GetFamilySymbolIds().First<ElementId>()) as FamilySymbol);
				if (!this.m_ESymbol.IsActive)
				{
					this.m_ESymbol.Activate();
				}
			}
		}

		private ViewPlan GetFirstLayer()
		{
			if (this.m_DicFloorLevels.Count == 0)
			{
				return this.m_DicFloorLevels.First<KeyValuePair<ViewPlan, bool>>().Key;
			}
			ViewPlan key = this.m_DicFloorLevels.First<KeyValuePair<ViewPlan, bool>>().Key;
			ViewPlan key2 = this.m_DicFloorLevels.Last<KeyValuePair<ViewPlan, bool>>().Key;
			double elevation = key.GenLevel.Elevation;
			double elevation2 = key2.GenLevel.Elevation;
			if (!Common.IsDoubleLessThanZero(elevation))
			{
				return key;
			}
			if (Common.IsDoubleLessThanZero(elevation2))
			{
				return key2;
			}
			IEnumerable<ViewPlan> enumerable = from l in this.m_DicFloorLevels.Keys
			where Common.IsDoubleEquals(l.GenLevel.Elevation, 0.0, 1E-09)
			select l;
			if (enumerable == null || enumerable.Count<ViewPlan>() == 0)
			{
				return null;
			}
			if (this.m_DicFloorLevels[enumerable.First<ViewPlan>()])
			{
				return enumerable.First<ViewPlan>();
			}
			return key;
		}

		public bool Execute()
		{
			ViewPlan firstLayer = this.GetFirstLayer();
			if (firstLayer == null)
			{
				YJKMessageBox.Show("请重新选中楼层，找不到首层!");
				return true;
			}
			CalHostForEachLayer calHostForEachLayer = new CalHostForEachLayer(this.m_doc, this.m_pt1, this.m_pt2, this.m_DicFloorLevels);
			Dictionary<ElementId, ElementId> dictionary = calHostForEachLayer.Execute();
			if (dictionary == null || dictionary.Count == 0)
			{
				YJKMessageBox.Show("没有找到要放置电梯的墙!");
				return true;
			}
			if (LoadFamily.GetInstance(this.m_CmdData) == null)
			{
				YJKMessageBox.Show("加载族失败!");
				return true;
			}
			Transaction transaction = new Transaction(this.m_doc, "放置电梯");
			transaction.Start();
			try
			{
				bool flag = this.SetAllElevator(firstLayer, dictionary);
				if (!flag)
				{
					YJKMessageBox.Show("布置电梯出错，请检查所选楼层是否存在可以布置电梯的墙!");
					transaction.RollBack();
					return false;
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
				return false;
			}
			return true;
		}

		private ExternalCommandData m_CmdData;

		private Document m_doc;

		private ElevatorSettingParam m_ElevatorSettings;

		private Dictionary<ViewPlan, bool> m_DicFloorLevels;

		private XYZ m_pt1;

		private XYZ m_pt2;

		private XYZ m_pt3;

		private FamilySymbol m_FistLayerESymbol;

		private FamilySymbol m_ESymbol;

		private double dOffset = Common.MMToFeet(150.0);
	}
}
